package com.jfinal.interceptor;

import com.jfinal.aop.Interceptor;
import com.jfinal.aop.Invocation;
import com.jfinal.constant.Const;
import com.jfinal.core.Controller;
import com.jfinal.model.auth.Auth;
import com.jfinal.model.auth.Role;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Record;
import com.jfinal.plugin.ehcache.CacheKit;
import org.apache.log4j.Logger;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * Created by xiaoyuan on 2018/1/19.
 */
public class AuthInterceptor implements Interceptor {
    public static Logger logger = Logger.getLogger(AuthInterceptor.class);
    @Override
    public void intercept(Invocation invocation) {
        if(invocation.isActionInvocation()){
            Controller controller = invocation.getController();
            String actionKey = invocation.getActionKey();
            //用于判断用户是否已经过期，主要是用于更改了用户的角色，下次操作时强制转到登陆界面
            String token = controller.getSessionAttr(Const.SESSION_TOKEN);
            if(token!=null&&!token.isEmpty()){
               List<String> shouldExpired = CacheKit.get("auth", "token");
               if(shouldExpired==null||!shouldExpired.contains(token)){
                   //前提是用户的角色已经放到session,并用逗号隔开
                   String roles_id = controller.getSessionAttr(Const.SESSION_ROLES_ID);
                   Map<Long,List<Auth>> role_auth = CacheKit.get("auth","all_role_auth");
                   if(role_auth==null){
                       role_auth = new HashMap<>();
                       List<Record> roles = Db.find(Db.getSql("auth.findAllValidRole"));
                       if(roles!=null){
                           for(Record role:roles){
                               Role r = new Role();
                               r.set("id",role.getLong("id"));
                               List<Auth> auths = r.getAuths();
                               if(auths==null){
                                   auths = new ArrayList<>();
                               }
                               role_auth.put(role.getLong("id"),auths);
                           }
                       }
                       CacheKit.put("auth","all_role_auth",role_auth);
                   }
                   if(roles_id!=null&&!roles_id.isEmpty()){
                       String[] roleIds = roles_id.split(",");
                       Integer i=0;
                       for(i=0;i<roleIds.length;i++){
                            if(role_auth.containsKey(Long.valueOf(roleIds[i]))){
                                List<Auth> auths = role_auth.get(Long.valueOf(roleIds[i]));
                                boolean find = false;
                                for(Auth auth:auths){
                                    if(auth.get("action").equals(actionKey)){
                                        find=true;
                                        break;
                                    }
                                }
                                if(find){
                                    break;
                                }
                            }
                       }
                       if(i==roleIds.length){
                           controller.renderError(403,"/403.html");
                       }else{
                           invocation.invoke();
                       }
                   }else{
                       controller.renderError(403,"/403.html");
                   }
               }else{

                   controller.redirect("/login");
               }
            }else{
                //无token就跳转到login,跳转到login页面时带上上一个页面，以便登录后回到上个页面
                String lastRequestURL = controller.getRequest().getRequestURL().toString();
                try {
                    controller.redirect("/login?forwardURL=" + URLEncoder.encode(lastRequestURL, "UTF-8"));
                } catch (UnsupportedEncodingException e) {
                    logger.error(e.getMessage());
                }
            }
        }else{
            invocation.invoke();
        }
    }
}
